/*
 Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.

 https://www.cocos.com/

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights to
 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 of the Software, and to permit persons to whom the Software is furnished to do so,
 subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
*/

import { _decorator, Node, Camera, find } from 'cc';
import { Singleton } from "../../util/Singleton";
import { Log } from "../../util/io/log";
import { UIBase } from "./ui-base";
import { Res } from "../res/res";
import { Msg } from '../../util/msg';
import { UtilNode } from '../../util/util';
import { DataGameInst } from '../../logic/data/data-core';
import { ResCache } from '../res/res-cache';
import { utils } from '../../util/util';

export class UI extends Singleton {
    private _map: { [name: string]: UIBase } = {};
    public node: Node | undefined | null;
    public panelRoot: Node | undefined;
    public camera: Camera | undefined;

    public init () {
        this.node = find('init/UIRoot');
        //设置根节点
        this.panelRoot = UtilNode.getChildByName(this.node!, 'panels');
        if (this.node === undefined || this.node == null) {
            throw new Error(`can not find canvas ui root.`);
        }

        //监听ui回收
        Msg.on('refresh_ui', this.refresh.bind(this));
        //监听ui面板开启
        Msg.on('msg_ui_on', this.on.bind(this));
        //监听ui面板关闭
        Msg.on('msg_ui_off', this.off.bind(this));

        //预加载预设的ui面板
        const cacheList = DataGameInst._data.ui_cache_list; //['ui_level', 'ui_level_end', 'ui_logo', 'ui_menu', 'ui_select_equips', 'ui_settings'];

        for (let i = 0; i < cacheList.length; i++) {
            this.load(cacheList[i]);
        }

        //获取相机ui
        this.camera = this.node?.getChildByName('Camera')?.getComponent(Camera)!;
    }

    public refresh () {
        for (let key in this._map) {
            this._map[key].refresh();
        }
    }

    //加载配置的全部ui面板
    public load (name: string) {
        const asset = ResCache.Instance.getPrefab(name);
        if (asset) {

            //实例化ui面板
            const panel = Res.inst(asset, UI.Instance.panelRoot);
            //获取面板层级
            const order = DataGameInst._data.ui_order[name];
            //设置面板位置
            panel.setPosition(0, 0, order);
            let set = false;
            //获取面板数量
            var count = UI.Instance.panelRoot.children.length;
            //设置面板层级
            for (let i = 1; i < count; i++) {
                let child = this.panelRoot!.children[i];
                //如果当前面板层级大于当前面板层级则设置当前面板层级
                if (child.position.z > order) {
                    let ui_order = i;
                    panel.setSiblingIndex(ui_order);
                    set = true;
                    break;
                }
            }
            //如果没有设置层级则设置在最上层
            if (!set) panel.setSiblingIndex(count);
            //实例化ui面板基类
            const uiBase = new UIBase(panel);
            //开启ui面板
            uiBase.on();
            this._map[name] = uiBase;
            //延迟关闭ui面板，为了预先加载防止ui面板闪烁
            utils.delay(() => {
                if (name == 'ui_logo') return;
                this._map[name].off();
            }, 0.05);
        } else {
            Log.warn('Can not load res : ' + name);
        }
    }

    //打开某个面板
    public on (name: string) {
        console.log('打开面板：' + name);
        var load = async () => {
            const panel = this._map[name];
            if (panel) {
                panel.on();
        console.log('打开面板1：' + name,panel);
    } else {
                Res.loadPrefab('ui/' + name, (err, asset) => {
                    if (asset) {
                        const panel = Res.inst(asset, UI.Instance.panelRoot);
                        const order = DataGameInst._data.ui_order[name];
                        panel.setPosition(0, 0, order);
                        let set = false;
                        var count = UI.Instance.panelRoot.children.length;
                        for (let i = 1; i < count; i++) {
                            let child = this.panelRoot!.children[i];
                            if (child.position.z > order) {
                                let ui_order = i;
                                panel.setSiblingIndex(ui_order);
                                set = true;
                                break;
                            }
                        }
                        if (!set) panel.setSiblingIndex(count);
                        const uiBase = new UIBase(panel);
                        uiBase.on();
                        this._map[name] = uiBase;
                    } else {
                        Log.warn('Can not load res : ' + name);
                    }
                });
            }
        };
        load();
    }

    //关闭某个面板
    public off (name: string) {
        const panel = this._map[name];
        if (panel) {
            panel.off();
        } else {
            //Log.warn('You want off a ui object that does not exist : ' + name);
        }
    }

    //销毁某个面板
    public destroy (name: string) {
        const panel = this._map[name];
        if (panel) {
            panel.destroy();
            this._map[name] = undefined;
        } else {
            Log.warn('You want destroy a ui object that does not exist. - ' + name);
        }
    }

}